#ifndef GAME_ANIMATION_TERRAIN_SHADER_H
#define GAME_ANIMATION_TERRAIN_SHADER_H
//
// Game Animation.
// Copyright (C) 2007 Department of Computer Science, University of Copenhagen
//
#include <animation/configuration.h>

#include <OpenTissue/gpu/cg/cg_program.h>
#include <OpenTissue/gpu/image/image.h>
#include <OpenTissue/gpu/image/io/image_read.h>
#include <OpenTissue/gpu/image/io/image_write.h>
#include <OpenTissue/gpu/image/image_make_noise.h>
#include <OpenTissue/gpu/texture/texture_texture2D.h>
#include <OpenTissue/gpu/texture/texture_create_texture2D.h>
#include <math.h>


namespace animation
{

  /**
  * The Terrain Shader.
  * Sets up rendering before drawing terrain geometry.
  */
  class TerrainShader
  {
  public:

    typedef boost::shared_ptr<OpenTissue::image::Image<unsigned char> > image_pointer;

  protected:

    OpenTissue::cg::Program       m_vertex_program;
    OpenTissue::cg::Program       m_fragment_program;
    image_pointer                 m_dirt_image;
    image_pointer                 m_grass_image;
    image_pointer                 m_fungus_image;
    image_pointer                 m_weight_image;
    OpenTissue::texture::texture2D_pointer m_grass_texture;
    OpenTissue::texture::texture2D_pointer m_dirt_texture;
    OpenTissue::texture::texture2D_pointer m_fungus_texture;

    image_pointer                 m_noise_image;
    OpenTissue::texture::texture2D_pointer m_noise_texture;

  public:
    void pre_render(bool reload,
		           float light_x,float light_y,float light_z,
				   float intensity,
								float fog_density,
	                            float fog_color_r, float fog_color_g, float fog_color_b)
    {
      //--- Load textures if they are not allready loaded
      if(!m_grass_image)
      {
        m_dirt_image.reset( new OpenTissue::image::Image<unsigned char>() );
        m_grass_image.reset( new OpenTissue::image::Image<unsigned char>() );
        m_fungus_image.reset( new OpenTissue::image::Image<unsigned char>() );
		m_noise_image.reset( new OpenTissue::image::Image<unsigned char>() );

        OpenTissue::image::read(demo_path + "TheSwampThing2008/data/dirt_layer.png",*m_dirt_image);
        OpenTissue::image::read(demo_path + "TheSwampThing2008/data/grass_layer.png",*m_grass_image);
        OpenTissue::image::read(demo_path + "TheSwampThing2008/data/fungus_layer.png",*m_fungus_image);
		OpenTissue::image::read(demo_path + "TheSwampThing2008/data/cloud_noise.png",*m_noise_image);
        m_dirt_texture = m_dirt_image->create_texture(GL_RGBA);
        m_grass_texture = m_grass_image->create_texture(GL_RGBA);
        m_fungus_texture = m_fungus_image->create_texture(GL_RGBA);
		m_noise_texture = m_noise_image->create_texture(GL_RGBA);

        m_dirt_texture->set_repeating(true);
        m_dirt_texture->set_mipmapping( true );
        m_grass_texture->set_repeating(true);
        m_grass_texture->set_mipmapping( true );
        m_fungus_texture->set_repeating(true);
        m_fungus_texture->set_mipmapping(true);
        m_noise_texture->set_repeating(true);
        m_noise_texture->set_mipmapping(true);
      }

      //--- Load vertex program, note that cg-program path is currently hardcoded, a
      //--- more sensible solution would be
      //---
      //---  std::string filename = get_environment_variable("OPENTISSUE") + .... + "vp_grass.cg";
      //---
      if(!m_vertex_program.is_program_loaded()||reload)
        m_vertex_program.load_from_file(OpenTissue::cg::Program::vertex_program,demo_path + "../animation/vp_terrain.cg");

      m_vertex_program.set_modelview_projection_matrix();
	  m_vertex_program.set_modelview_inverse_transpose();
	  m_vertex_program.set_float_param("light_vec",light_x,light_y,light_z);
	  m_vertex_program.set_float_param("intensity",intensity);
      //--- load fragment program
      if(!m_fragment_program.is_program_loaded()||reload)
        m_fragment_program.load_from_file(OpenTissue::cg::Program::fragment_program,demo_path + "../animation/fp_terrain.cg");

      m_fragment_program.set_input_texture( "fungus_texture", m_fungus_texture );
      m_fragment_program.set_input_texture( "dirt_texture",   m_dirt_texture   );
      m_fragment_program.set_input_texture( "grass_texture",  m_grass_texture  );
      m_fragment_program.set_input_texture( "noise_texture",  m_noise_texture  );
	  m_fragment_program.set_float_param( "fog_density",  fog_density  );
	  m_fragment_program.set_float_param( "fog_color",  fog_color_r,fog_color_g,fog_color_b);

      //--- Setup openGL state
      //glEnable(GL_CULL_FACE);
    }

    void enable()
    {
      m_vertex_program.enable();
      m_fragment_program.enable();
	  glEnable(GL_CULL_FACE);
    }
    void disable()
    {
      m_vertex_program.disable();
      m_fragment_program.disable();
	  glDisable(GL_CULL_FACE);
    }
  };

} // namespace animation

// GAME_ANIMATION_TERRAIN_SHADER_H
#endif
